package com.wm.blog_web.service;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.wm.blog_common.base.BeanUtils;
import com.wm.blog_common.bean.PageHelper;
import com.wm.blog_common.bean.QueryPage;
import com.wm.blog_common.constatnt.CommonConstant;
import com.wm.blog_common.constatnt.ErrorConstant;
import com.wm.blog_common.domain.TUserDO;
import com.wm.blog_common.entity.TUser;
import com.wm.blog_common.enums.Emaillag;
import com.wm.blog_common.enums.LoginType;
import com.wm.blog_common.result.Result;
import com.wm.blog_common.util.*;
import com.wm.blog_web.dao.TUserDAO;
import com.wm.blog_web.query.TUserQuery;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 用户表 服务实现类
 * </p>
 *
 * @author 半卷流年
 * @since 2020-03-24
 */
@Service
public class TUserService {
    @Autowired
    private TUserDAO tUserDAO;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Autowired
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;


    /**
     * 根据ID查询
     *
     * @param id
     * @return
     */
    public Result<TUserDO> selectById(Long id) {
        return Result.success(BeanUtils.copyProperties(tUserDAO.getById(id), TUserDO.class));
    }

    /**
     * 根据ID删除
     *
     * @param id
     * @return
     */
    public Result deleteById(Long id) {
        return tUserDAO.removeById(id) ? Result.success() : Result.failure();
    }

    /**
     * 添加
     *
     * @param tUser
     * @return
     */
    public Result insert(TUser tUser) {
        return tUserDAO.save(tUser) ? Result.success() : Result.failure();
    }

    /**
     * 修改
     *
     * @param tUser
     * @return
     */
    public Result update(TUser tUser) {
        return tUserDAO.updateById(tUser) ? Result.success() : Result.failure();
    }

    /**
     * 统计总数
     *
     * @param query
     * @return
     */
    public Result<Integer> count(TUserQuery query) {
        return Result.success(tUserDAO.count(this.combineQuery(query)));
    }

    /**
     * 列表查询
     *
     * @param query
     * @return
     */
    public Result<List<TUserDO>> list(TUserQuery query) {
        return Result.success(BeanUtils.copyListProperties(tUserDAO.list(this.combineQuery(query)), TUserDO.class));
    }

    /**
     * 分页查询
     *
     * @param page
     * @return
     */
    public Result<Page<TUserDO>> page(QueryPage page, TUserQuery query) {
        return Result.success(PageHelper.newPage(tUserDAO.page(page, this.combineQuery(query)), TUserDO.class));
    }

    /**
     * 组装查询条件
     *
     * @param query
     * @return
     */
    private QueryWrapper<TUser> combineQuery(TUserQuery query) {
        QueryWrapper<TUser> wrapper = new QueryWrapper<>();
        Optional.ofNullable(query).ifPresent(x -> {
            Optional.ofNullable(x.getUsername()).filter(StringUtils::isNotEmpty).ifPresent(y -> {
                wrapper.like("user_name", y);
            });
            Optional.ofNullable(x.getPassword()).filter(StringUtils::isNotEmpty).ifPresent(y -> {
                wrapper.eq("pass_word", y);
            });
        });
        return wrapper;
    }


    /**
     * 用户注册
     *
     * @param query
     * @return
     */
    public Result regist(TUserQuery query, HttpServletRequest request) {
        query = Optional.ofNullable(query).orElse(new TUserQuery());
        //字段校验
        Result<String> validate = ObjectValidateUtil.validate(query, new ArrayList<String>() {{
            add("imageCode");
        }});
        if (!validate.isSuccess()) {
            return validate;
        }
        if (!StringUtils.equals(query.getPassword(), query.getConfirmPass())) {
            return Result.failure(ErrorConstant.PW_CONFIRM_ERROR);
        }
        //校验手机
        if (!CommonValidUtil.checkMobile(query.getMobile())) {
            return Result.failure(ErrorConstant.MOBILE_ILLEGAL);
        }
        //TOdo 校验短信验证码是否正确
        //校验用户名是否已经存在
        Result result = this.checkUserNameExsit(query.getUsername());
        if (!result.isSuccess()) {
            return Result.failure(ErrorConstant.USER_NAME_EXSIT);
        }
        String ipAddress = IpUtil.getIpAddress(request);
        TUser user = new TUser();
        BeanUtils.copyProperties(query, user);
        user.setUserName(query.getUsername());
        user.setPassWord(query.getPassword());
        user.setIpSource(ipAddress);
        //默认需要开启邮件通知
        user.setStartEmailNotification(Emaillag.ENABLE.getValue());
        return tUserDAO.save(user) ? Result.success() : Result.failure();
    }


    /**
     * 校验用户名是否已经存在
     */
    private Result checkUserNameExsit(String userName) {
        if (StringUtil.isEmpty(userName)) {
            return Result.success();
        }
        QueryWrapper<TUser> wrapper = new QueryWrapper<>();
        wrapper.eq("user_name", userName);
        wrapper.last("limit 1");
        TUser user = Optional
                .ofNullable(tUserDAO.getOne(wrapper))
                .orElse(new TUser());
        return ObjectUtils.isEmpty(user.getId()) ? Result.success() : Result.failure();

    }


    /**
     * 保存验证码到redis
     *
     * @param random
     * @param text
     */
    public void saveImageCode(String random, String text) {
        String key = CommonConstant.WEB_REDIS_PREFIX + random;
        redisTemplate.opsForValue().set(key, text, CommonConstant.CODE_REDIS_KEY_EXPIRE, TimeUnit.SECONDS);
    }


    /**
     * 登录
     *
     * @param query
     * @param request
     * @return
     */
    public Result login(TUserQuery query, HttpServletRequest request) {
        query = Optional.ofNullable(query).orElse(new TUserQuery());
        if (ObjectUtils.isEmpty(query) || (!LoginType.contains(query.getLoginType()))) {
            return Result.failure(ErrorConstant.LOGIN_TYPE_ERROR);
        }
        if (LoginType.PASSWORD_LOGIN.getValue().equals(query.getLoginType())) {
            //账号密码登录
            Result<String> validate = ObjectValidateUtil.validate(query, new ArrayList<String>() {{
                add("mobile");
                add("code");
                add("confirmPass");
            }});
            if (!validate.isSuccess()) {
                return validate;
            }
            if (StringUtils.isEmpty(query.getRandom())) {
                return Result.failure(ErrorConstant.IMAGE_CODE_RANDOM);
            }
            String key = CommonConstant.WEB_REDIS_PREFIX + query.getRandom();
            //校验验证码
            String imageCode = redisTemplate.opsForValue().get(key);
            if (!StringUtils.equals(imageCode, query.getImgCode())) {
                return Result.failure(ErrorConstant.IMAGE_CODE_CHECK_ERROR);
            }
            TUser account = this.checkAccount(query.getUsername(), query.getPassword());
            //校验账号密码    TODO 密码加密
            if (ObjectUtils.isNotEmpty(account.getId())) {
                //更新登录信息
                CompletableFuture.runAsync(() -> {
                    String address = IpUtil.getIpAddress(request);
                    Date currentDate = DateUtil.getCurrentDate();
                    account.setLastLoginIp(address);
                    account.setLastLoginTime(currentDate);
                    account.setLoginCount(account.getLoginCount() + 1);
                    tUserDAO.updateById(account);
                }, threadPoolTaskExecutor);
                TUserDO userDO = BeanUtils.copyProperties(account, TUserDO.class);
                String token = CommonUtil.createToken();
                userDO.setToken(token);
                //设置token到redis
                redisTemplate.opsForValue().set(CommonConstant.WEB_REDIS_PREFIX + token, account.getId() + "", CommonConstant.WEB_LOGIN_REDIS_EXPIRE, TimeUnit.SECONDS);
                return Result.success(userDO);
            }
        } else {
            //手机号登录 todo
        }
        return Result.failure(ErrorConstant.USER_USERNAME_PASSWORD_ERROR);
    }


    private TUser checkAccount(String username, String password) {
        if (StringUtils.isNotEmpty(username) && StringUtils.isNotEmpty(password)) {
            QueryWrapper<TUser> wrapper = new QueryWrapper<>();
            wrapper.eq("user_name", username);
            wrapper.eq("pass_word", password);
            wrapper.last(" limit 1");
            return Optional
                    .ofNullable(tUserDAO.getOne(wrapper))
                    .orElse(new TUser());
        }
        return new TUser();
    }


    /**
     * 修改密码
     *
     * @param query
     * @return
     */
    public Result editPassword(TUserQuery query) {
        query = Optional.ofNullable(query).orElse(new TUserQuery());
        if (ObjectUtils.isEmpty(query.getUserId())) {
            return Result.failure(ErrorConstant.USER_ID_EMPTY);
        }
        if (StringUtils.isEmpty(query.getOldPassword()) || StringUtils.isEmpty(query.getConfirmPass()) || StringUtils.isEmpty(query.getPassword())) {
            return Result.failure(ErrorConstant.PASSWORD_EMPTY);
        }
        if (StringUtils.equals(query.getPassword(), query.getConfirmPass())) {
            return Result.failure(ErrorConstant.PW_CONFIRM_ERROR);
        }
        if (StringUtils.equals(query.getOldPassword(), query.getPassword())) {
            return Result.failure(ErrorConstant.OLD_NEW_PASSWORD_SAME
            );
        }
        //密码校验
        TUser user = Optional
                .ofNullable(tUserDAO.getById(query.getUserId()))
                .orElse(new TUser());
        if (!StringUtils.equals(query.getOldPassword(), user.getPassWord())) {
            return Result.failure(ErrorConstant.OLD_PASSWORD_ERROR);
        }
        user.setPassWord(query.getPassword());
        return tUserDAO.updateById(user) ? Result.success() : Result.failure();
    }

    /**
     * 刷新token
     *
     * @param token
     * @return
     */
    public Result refresh(String token, Long userId) {
        if (StringUtil.isEmpty(token)) {
            return Result.failure(ErrorConstant.TOKEN_EMPTY);
        }
        if (ObjectUtils.isNotEmpty(userId)) {
            return Result.failure(ErrorConstant.USER_ID_EMPTY);
        }
        String key = CommonConstant.WEB_REDIS_PREFIX + token;
        redisTemplate.delete(key);
        String newKey = CommonConstant.WEB_REDIS_PREFIX + CommonUtil.createToken();
        redisTemplate.opsForValue().set(newKey, String.valueOf(userId));
        return Result.success(token);
    }

    /**
     * 查询当前登录人的信息
     * @param userId
     * @return
     */
    public Result currentInfo(Long userId) {
        if(ObjectUtils.isEmpty(userId) || -1 == userId){
            return Result.success();
        }
        return Result.success(tUserDAO.getById(userId));
    }
}







